package com.ccteam.shared.data.home

import com.ccteam.model.PageVO
import com.ccteam.model.Resource
import com.ccteam.model.album.AlbumSimplifyVO
import com.ccteam.model.banner.BannerVO
import com.ccteam.model.music.MusicVO
import com.ccteam.model.playlistsheet.PlaylistSheetVO
import com.ccteam.network.ApiResult
import com.ccteam.network.ResultVO
import com.ccteam.shared.api.OnlineMusicHomeDataSource
import com.ccteam.shared.data.BaseBoundResource
import com.ccteam.shared.data.album.NewAlbumPagingSource
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import javax.inject.Inject
import javax.inject.Singleton

/**
 * @author Xiaoc
 * @since 2021/1/30
 *
 * 在线音乐首页 仓库层
 **/
@Singleton
class OnlineMusicHomeRepository @Inject constructor(
    private val onlineMusicHomeDataSource: OnlineMusicHomeDataSource
) {

    private var bannerData: List<BannerVO> = mutableListOf()
    private var albumData: List<AlbumSimplifyVO> = mutableListOf()
    private var musicData: List<MusicVO> = mutableListOf()
    private var hotPlaylistSheetData: List<PlaylistSheetVO> = mutableListOf()
    private var hotMusicData: List<HotMusicData> = mutableListOf()

    /**
     * 得到轮播图的具体内容
     * 该内容采用内存存储缓存
     *
     * @return  Flow流的结果集，封装的是 List<[BannerVO]>
     */
    fun getBanner(): Flow<Resource<List<BannerVO>>> {
        return object: BaseBoundResource<List<BannerVO>, ResultVO<PageVO<BannerVO>>>(){
            override fun loadFromDbOrMemory(): Flow<List<BannerVO>> {
                return flow { emit(bannerData) }
            }

            override suspend fun saveNetworkResult(item: ResultVO<PageVO<BannerVO>>) {
                bannerData = item.data?.records ?: mutableListOf()
            }

            override fun shouldFetch(data: List<BannerVO>?): Boolean {
                return true
            }

            override suspend fun fetchFromNetwork(): ApiResult<ResultVO<PageVO<BannerVO>>> = onlineMusicHomeDataSource.getBanner(1,5)

        }.asFlow()
    }

    /**
     * 得到新专推荐的具体内容
     * 该内容采用内存存储缓存
     *
     * @return Flow流的结果集，封装的是 List<[AlbumSimplifyVO]>
     */
    fun getNewAlbumRecommend(): Flow<Resource<List<AlbumSimplifyVO>>> {
        return object: BaseBoundResource<List<AlbumSimplifyVO>,ResultVO<PageVO<AlbumSimplifyVO>>>(){
            override fun loadFromDbOrMemory(): Flow<List<AlbumSimplifyVO>> {
                return flow { emit(albumData) }
            }

            override suspend fun saveNetworkResult(item: ResultVO<PageVO<AlbumSimplifyVO>>) {
                albumData = item.data?.records ?: mutableListOf()
            }

            override fun shouldFetch(data: List<AlbumSimplifyVO>?): Boolean {
                return true
            }

            override suspend fun fetchFromNetwork(): ApiResult<ResultVO<PageVO<AlbumSimplifyVO>>> {
                return onlineMusicHomeDataSource.getNewAlbums(1,5)
            }

        }.asFlow()
    }

    /**
     * 得到新歌推荐的具体内容
     * 该内容采用内存存储缓存
     *
     * @return Flow流的结果集，封装的是 List<[MusicVO]>
     */
    fun getNewMusicRecommend(): Flow<Resource<List<MusicVO>>>{
        return object: BaseBoundResource<List<MusicVO>,ResultVO<PageVO<MusicVO>>>(){
            override fun loadFromDbOrMemory(): Flow<List<MusicVO>> {
                return flow { emit(musicData) }
            }

            override suspend fun saveNetworkResult(item: ResultVO<PageVO<MusicVO>>) {
                musicData = item.data?.records ?: mutableListOf()
            }

            override fun shouldFetch(data: List<MusicVO>?): Boolean {
                return true
            }

            override suspend fun fetchFromNetwork(): ApiResult<ResultVO<PageVO<MusicVO>>> {
                return onlineMusicHomeDataSource.getNewMusic(1,5)
            }

        }.asFlow()
    }

    /**
     * 得到热门歌单推荐的具体内容
     * 该内容采用内存存储缓存
     *
     * @return Flow流的结果集，封装的是 List<[PlaylistSheetVO]>
     */
    fun getHotPlaylistSheetRecommend(): Flow<Resource<List<PlaylistSheetVO>>>{
        return object: BaseBoundResource<List<PlaylistSheetVO>,ResultVO<List<PlaylistSheetVO>>>(){
            override fun loadFromDbOrMemory(): Flow<List<PlaylistSheetVO>> {
                return flow { emit(hotPlaylistSheetData) }
            }

            override suspend fun saveNetworkResult(item: ResultVO<List<PlaylistSheetVO>>) {
                hotPlaylistSheetData = item.data ?: mutableListOf()
            }

            override fun shouldFetch(data: List<PlaylistSheetVO>?): Boolean {
                return true
            }

            override suspend fun fetchFromNetwork(): ApiResult<ResultVO<List<PlaylistSheetVO>>> {
                return onlineMusicHomeDataSource.getHotPlaylistSheet(0,10)
            }

        }.asFlow()
    }

    /**
     * 得到热门歌曲推荐的具体内容
     * 该内容采用内存存储缓存
     *
     * @return Flow流的结果集，封装的是 List<[MusicVO]>
     */
    fun getHotMusicRecommend(): Flow<Resource<List<HotMusicData>>>{
        return object: BaseBoundResource<List<HotMusicData>,ResultVO<List<MusicVO>>>(){
            override fun loadFromDbOrMemory(): Flow<List<HotMusicData>> {
                return flow { emit(hotMusicData) }
            }

            override suspend fun saveNetworkResult(item: ResultVO<List<MusicVO>>) {
                hotMusicData = item.data?.map {
                    HotMusicData(it)
                } ?: emptyList()
            }

            override fun shouldFetch(data: List<HotMusicData>?): Boolean {
                return true
            }

            override suspend fun fetchFromNetwork(): ApiResult<ResultVO<List<MusicVO>>> {
                return onlineMusicHomeDataSource.getHotSong(0,10)
            }

        }.asFlow()
    }

    /**
     * 添加热门歌曲计数
     * @param id 歌曲ID
     */
    suspend fun addHotMusicCount(id: String): ApiResult<ResultVO<Nothing>>{
        return onlineMusicHomeDataSource.addHotMusicCount(id)
    }

    /**
     * 添加热门歌单计数
     * @param id 歌单ID
     */
    suspend fun addHotPlaylistSheetCount(id: String): ApiResult<ResultVO<Nothing>>{
        return onlineMusicHomeDataSource.addHotPlaylistSheetCount(id)
    }

    data class HotMusicData(
        val music: MusicVO
    )
}